#include "ExecCommand.h"
#include <iostream>
#include <sstream>
#include "util.h"
#include "Phnqlet.h"
#include "PhnqletManager.h"
#include "Tag.h"
#include "Template.h"
#include "jsmin.h"
#include "ObjectFactory.h"

namespace phnq
{
	namespace phnqlets
	{
		void ExecCommand::execute(string relPath, map<string,string> params, processor_response *response)
		{
			UTHObject *obj = NULL;
		
			util_replace_all(relPath, ".js", "");
		
			if(relPath == "load")
			{
				obj = load(params);
			}
			else if(relPath == "data")
			{
				obj = data(params);
			}
			else
			{
				response->status = STATUS_BAD_REQUEST;
				return;
			}
		
			if(!obj)
				response->status = STATUS_NOT_FOUND;

			string resp = "phnq.io.execResults["+params["execId"]+"]="+obj->toString()+";";
			
			response->bodyStream = new istringstream(resp);
			
			obj->release();
		}
		
		UTHObject* ExecCommand::data(map<string,string> params)
		{
			vector<string> argStrs = util_split_string(params["args"], ",");
			UTHArray *args = new UTHArray();
			for(vector<string>::iterator it=argStrs.begin(); it!=argStrs.end(); it++)
			{
				UTHString *arg = new UTHString(it->c_str());
				args->add(arg);
				arg->release();
			}
			UTHObject *dataObj = ObjectFactory::getCurrent()->createObject(args);
			args->release();
			return dataObj;
		}
	
		UTHObject* ExecCommand::load(map<string,string> params)
		{
			set<Tag*> tags;
			set<Phnqlet*> phnqlets;
			stringbuf tmpltBuf, scriptBuf, styleBuf;
			UTHObject *obj = new UTHObject();
		
			vector<string> types = util_split_string(params["types"], ",");
		
			set<int> loadedPhnqtionIds = util_expand_bitset(params["loadedPhnqtions"]);
			set<int> loadedTmpltIds = util_expand_bitset(params["loadedTmplts"]);
		
			for(set<int>::iterator it=loadedTmpltIds.begin(); it!=loadedTmpltIds.end(); it++)
			{
				cout << "loadedTmpltIds: " << *it << endl;
			}
		
			for(vector<string>::iterator it=types.begin(); it!=types.end(); it++)
			{
				string type = *it;
			
				Phnqlet *p = PhnqletManager::getInstance()->get(type);
				if(p)
				{
					Template *t = p->getTemplate("main");
					t->insertObjectCodeAndDependencies(tmpltBuf, phnqlets, tags, &loadedTmpltIds);
				}
			}
		
			for(set<Phnqlet*>::iterator it=phnqlets.begin(); it!=phnqlets.end(); it++)
			{
				Phnqlet *p = *it;
			
				if(loadedPhnqtionIds.find(p->getIndex()) == loadedPhnqtionIds.end())
				{
					string script = p->getScript();
					string style = p->getStyle();
			
					scriptBuf.sputn(script.c_str(), script.length());
					styleBuf.sputn(style.c_str(), style.length());
				}
			}
		
			UTHString *tmpltStr = new UTHString(jsmin(tmpltBuf.str()).c_str());
			UTHString *scriptStr = new UTHString(scriptBuf.str().c_str());
			UTHString *styleStr = new UTHString(styleBuf.str().c_str());
		
			obj->set("tmplt", tmpltStr);
			obj->set("script", scriptStr);
			obj->set("style", styleStr);
		
			tmpltStr->release();
			scriptStr->release();
			styleStr->release();
		
			return obj;
		}
	}
}
